//Forever|Next - 1k intro - AEONnano by triebkraft
//psndcj: 08-13.03.09

// feel the power of ROM =)

// sorry - all coments on russian language =)

// assemble by sjasm 1.07 stable [build 31.05.2007]

// исходники в жутком виде =( но общее представление получить для интересующихся можно...


	DEVICE ZXSPECTRUM128
	SLOT 3
			

//////////////////////////////////////////////////переменные эффекта
; переменные эффекта

pic		equ #8000//[#0800] сгенеренная текстура
mirr_tb	equ #9000//[#0100] таблица зеркалирования
start	equ #b400
imtab	equ #be00// прерывания

//////////////////////////////////////////////////эффект
        org start
        
        di
//генерим таблицу зеркалирования
	ld hl,mirr_tb,sp,hl
mirrgen1	ld a,l,b,8
1	rra:rl c:djnz 1b
	ld (hl),c:inc l:jr nz,mirrgen1

// прерывания
	ld hl,imtab:ld a,h,i,a
	im 2
	inc a
	ld (hl),a:inc l:jr nz,$-2
	inc h:ld (hl),a
	ld l,h:ld (hl),#c3:inc hl	//код команды JP #xxxx
	ld (hl),low obrab:inc hl
	ld (hl),high obrab

	ld a,#18+5	
		
part_loop
	ei:halt
	
	xor #0a:push af
	
	ld bc,#7ffd:out (c),a
	

		
//	ld hl,move+1:ld a,(hl):add 3:ld (hl),a:jp nc,continue
	ld hl,move+1:ld a,(hl):rlca:rlca:rlca:and 7:add 3:add (hl):ld (hl),a:jp nc,continue	
// новый эффект
	ld a,#17:out (c),a	
	
t_col	ld a,-1:inc a:and 7
	cp 2:jr c,$+4:ld a,7
	ld (t_col+1),a
	out (#fe),a
	ld e,a
	add a:add a:add a
		ld (back_col+1),a
	add e
	
	ld hl,#d800,de,#d801,(hl),a,b,4:ldir
	ld d,#5b,b,5:lddr
	
rnd	ld hl,#1105,d,high pic
gen2	ld c,(hl)//ld a,(hl):or #ff:ld c,a
gen1	ld a,(hl):and c:rlc c:ld (de),a:inc hl,e:jr nz,gen1

// печатаем буквы наугад
prnt	ld hx,30
1	ld e,(hl):inc hl
	ld c,e,b,#3e,lx,8
2	ld a,(bc),(de),a:inc e:rrca:ld (de),a:inc e,c:dec lx:jr nz,2b
	dec hx:jr nz,1b
	inc d:ld e,0
	bit 2,d:jr z,gen2
	
genc1	ld e,(hl),c,11
genc2	
// стираем пикселы для предотвращения клэшинга
	push de
	res 2,d:xor a
	ld b,8
1	ld (de),a:inc e:djnz 1b
	pop de

	ld a,(hl):and #7:inc hl
back_col	add 0:or #40
	ld b,3*8	
1	ld (de),a:inc e:djnz 1b
	dec c:jr nz,genc2
	inc d:bit 3,d:jr z,genc1
	
	ld c,(hl):add hl,bc:res 5,h
		ld (rnd+1),hl

	
continue

	
// выводим треугольник на экран
move	ld de,pic+#ff

project	// выводим треугольник на экран
	ld l,#00,a,8
proj1	ld b,a:exa
	push hl,de,hl,de,bc
proj2	ld h,#c8
	dup 7
	ld a,(de),(hl),a:inc e,h
	edup
	ld a,(de),(hl),a:inc e
	ld a,l:add #20:ld l,a
	djnz proj2
	pop bc,de,hl
	ld h,#d9
	set 2,d
proj3
	ld a,(de),(hl),a
	ld a,e:add 8:ld e,a
	ld a,l:add #20:ld l,a
	djnz proj3
	pop de,hl
	ld a,l:add #21:ld l,a
	inc d:ld a,e:add #8:ld e,a
	exa:dec a,a:jr nz,proj1

// обрабатываем углы 
//	ld e,#00,hl,turn1,a,#20+1:call angl_mode
	ld e,a,hl,turn1,a,#20+1:call angl_mode
	ld e,#83,hl,turn2,a,#20-1:call angl_mode
	
	
	ld a,#21:ld (univ_m4+1),a
// зеркалим верхний треугольник на 90' относительно левого
		ld de,#0120,hl,rot_cell,c,6,a,#20:call universal1	//up
	ld a,-#21:ld (univ_m4+1),a
	ld a,#20:ld (univ_m1+1),a
// зеркалим правый треугольник по обеим осям относительно левого
		ld de,#00e7,a,-#20:call universal		//right
	ld a,1:ld (univ_m1+1),a
// зеркалим нижний треугольник по обеим осям относительно верхнего
		ld de,#01e6,a,-1:call universal			//down

// атрибуты
	call atr_flip
	
square	// зеркалим соседний квадрат 8х8
	ld l,#00,e,#0f,a,8,b,high mirr_tb
square1	ld lx,8:exa
	push hl,de
1	//call mirror
mirror	//зеркалируем знакоместо по горизонтали
	ld h,#c8,d,h
	dup 7
	ld c,(hl),a,(bc),(de),a:inc h:inc d
	edup
	ld c,(hl),a,(bc),(de),a
//	ret

	inc l
	dec e
	dec lx:jr nz,1b
	pop de,hl
	ld a,l:add #20:ld l,a
	ld a,e:add #20:ld e,a
	exa:dec a:jr nz,square1


//	ld hl,#d900,de,#d90f,c,8,a,#20:call mirr_atr
	ld h,#d9,d,h,c,8,a,#20:call mirr_atr	//L и E остались нужными после предыдущей процедуры
	
// копирование
	ld de,#c810,h,d,c,#40:call copy_in	//ld hl,#c800
	ld l,#48
	ld de,#c040:call copy
	ld de,#c050:call copy
	ld l,#08
	ld de,#d000:call copy
	ld de,#d010:call copy

	pop af	//номер банки и экрана
	jp part_loop
	
	
	
copy	//копируем квадрат
	ld c,#30
copy_in
	push hl,hl,de,bc
copy1	push hl,de
		dup 16
	ld a,(hl),(de),a:inc l,e
		edup
	pop de,hl
	inc h:inc d:ld a,h:and 7:jr nz,2f
	ld a,h:sub 8:ld h,a
	ld a,d:sub 8:ld d,a
	ld a,l:add #20:ld l,a
	ld a,e:add #20:ld e,a	
2
	dec c:jr nz,copy1
	
	pop bc,de,hl
	ld b,#10
	ld h,#d9
	ld a,d:rra:rra:rra:and 3:add #d8:ld d,a
copy2	push hl,de,bc
1	ld a,(hl),(de),a:inc l,e:djnz 1b
	pop bc,de,hl
	ld a,l:add #20:ld l,a
	ld a,e:add #20:ld e,a	
2
	ld a,c:sub 8:ld c,a:jr nz,copy2
	pop hl:ret
		
			

	

universal	//универсальная процедура зеркалирования (настраивается для каждого случая)
	ld c,8,hl,mirrcell
universal1
	ld (univ_m3+1),hl,(univ_m2+1),a
	ld a,c
	ld l,d,b,high mirr_tb
univ1	ld lx,a:exa
	push hl,de
1	
univ_m3		call 0
	ld a,l
univ_m1	add #01:ld l,a
	ld a,e
univ_m2	add #20:ld e,a
	dec lx:jr nz,1b
	pop de,hl
	ld a,l:add #21:ld l,a
	ld a,e
univ_m4	add #21:ld e,a
	exa:dec a,a:jr nz,univ1
	ret

	
	
	
mirrcell	//зеркалируем знакоместо по обоим осям
	ld h,#c8,d,#c8+7
1	ld c,(hl),a,(bc),(de),a:inc h:dec d:bit 4,h:jp z,1b
	ret

	

		
	

angl_mode	//общая рутина для уголков
	ld (angl_m+1),hl,(angl_a+1),a,b,4
angl_mode1
		push bc
angl_m	call 0
angl_a	ld a,0:add e:ld e,a
		pop bc:djnz angl_mode1
		ret

turn2	//извратный метод для экономии памяти
// переворачиваем знакоместо - получаем уголок - переворачиваем обратно
	call flip
	call turn1
	
flip	//переворот знакоместа
	ld d,#c8,h,#c8+7,l,e
	ld b,4
flip1	ld a,(hl):exa:ld a,(de),(hl),a:exa:ld (de),a
	dec h:inc d:djnz flip1
	ret


			
turn1	//зеркалим уголок вправо-вверх
	ld d,#c8,hl,de,b,8
1	ld a,(hl):rlca:rl c:inc h:djnz 1b
	ld a,c,(de),a:inc d:dec h
				
 	ld a,(de):and #c0:ld bc,#0601
1	bit 6,(hl):jr z,$+2+1:or c:dec h:rlc c:djnz 1b
 	ld (de),a:inc d,h,h

	ld a,(de):and #e0:ld bc,#0510
1	bit 5,(hl):jr z,$+2+1:or c:dec h:rrc c:djnz 1b
	ld (de),a:inc d:dec h

	ld a,(de):and #f0:ld bc,#0401
1	bit 4,(hl):jr z,$+2+1:or c:dec h:rlc c:djnz 1b
	ld (de),a:inc d,h,h

	ld a,(de):and #e0:ld bc,#0304
1	bit 3,(hl):jr z,$+2+1:or c:dec h:rrc c:djnz 1b
	ld (de),a:inc d:dec h

	ld a,(de):and #fc
	bit 2,(hl):jr z,$+2+2:or #01:	dec h
	bit 2,(hl):jr z,$+2+2:or #02
	ld (de),a:inc d,h
	
	ld a,(de)
	bit 1,(hl):jr z,$+2+2:or 1
	ld (de),a
	
	ret
		
rot_cell	// поворачиваем знакоместо на 90 градусов	
	ld b,#80
	ld h,#c8
1
	ld d,#c8
		dup 7
	ld a,(de):and b:jr z,$+3:scf:rl c:inc d
		edup
	ld a,(de):and b:jr z,$+3:scf:rl c
	ld (hl),c:inc h
	rrc b:jr nc,1b
	ret
	

	

        
//////////////////////////////////////////////////инсталляция


atr_flip	//раскопирываем атрибуты
	ld bc,#0620,hl,atr_tb,d,#d9
atrflip1	push bc
1
	ld e,c:ld a,(de)
	ld e,(hl):inc hl
	ld (de),a
	ld a,c:add #20:ld c,a
	djnz 1b
//
	pop bc
	ld a,c:add #21:ld c,a
	dec b,b:jr nz,atrflip1
//
	ld e,#e7,hl,#d900,c,4,a,-#20

mirr_atr	// зеркалим атрибуты относительно вертикали
	ld lx,8,(mirr_atr_m+2),a
1	ld b,c:push hl,de
2	ld a,(hl),(de),a:inc l:dec e:djnz 2b
	pop de,hl	
	ld a,l:add #20:ld l,a
mirr_atr_m	ld a,e:add #20:ld e,a
	dec lx:jr nz,1b
	ret

atr_tb	//таблица атрибутов
	db #01,#02,#03,#e3,#e2,#e1
	db #22,#23,#c3,#c2
	db #43,#a3

obrab	//обработчик прерываний - музыка
	push hl,bc,af
////////////////
musdelay	ld a,1:dec a:jr z,music
delay_set	ld (musdelay+1),a
	jr obrab_e
music	ld hl,track:ld a,(hl):inc hl
	and a:jr nz,mus_cont
supervisor	ld a,0:inc a:and #1f:ld (supervisor+1),a
 	cp #8:ld a,#12:jr c,$+2+2:ld a,#10
 		ld (note_control+1),a
	ld l,low track:jr music+3
mus_cont
	ld (music+1),hl
// проверка на паузу
	cp 11:jr c,delay_set
//играем ноту
	ld l,a
1	ld a,(hl):push af:inc hl:and #0f
	ld bc,#fffd:out (c),a
	ld b,#bf,a,(hl):out (c),a
	inc hl
	pop af:rla:jr nc,1b
	
///////////////
obrab_e
	pop af,bc,hl
	ei:ret
	
	//align #100	//выравнивание не нужно - главное чтобы ноты и описатель попадали в один сектор
track	//описатель музона
	db low note00,low note01,low note02,low note03
	db 6
	db low note10
	db 9
	db low note00,low note01,low note02,low note03
	db 6
	db low note00,low note01,low note02,low note03
	db 6
	db low note10
	db 9
	db 0

note_control	
note00	db #07,#12,#02,#72,#03,#02,#89,#0f
note01	db #02,#e5,#83,#04
note02	db #02,#88,#03,#06,#89,#0a
note03	db #02,#ca,#83,#09
note10	db #09,#1a,#0b,#4e,#8d,#0c

	
	

	
e_eff
/////////////////////////////////////////////////load blocks

	savebin "intro.cod",start,e_eff-start
	

/////////////////////////////////////////////////save snapshot 
	SAVESNA "demo.sna",start
	
	LABELSLIST "labels.txt"